﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcMovieCollection.Properties;

namespace MvcMovieCollection.Controllers
{
    public class MemberFeaturesController : Controller
    {
        
        #region Properties/Members

        // Web Service object. Used for all DB access.
        private SvcMovies svcMovies;
        public SvcMovies SvcMovies
        {
            get
            {
                if (svcMovies == null)
                {
                    svcMovies = new SvcMovies();
                }

                return svcMovies;
            }
        }

        private string errorMessage;
        public string ErrorMessage
        {
            get
            {
                if (errorMessage == null)
                    return string.Empty;

                return errorMessage;
            }

            set
            {
                errorMessage = value;
            }
        }

        #endregion

        #region Action Results

        public ActionResult Index()
        {
            return View();
        }

        /// <summary>Action result for Movie page.
        /// calls down to webservice to get movies list.
        /// </summary>
        /// <returns></returns>
        public ActionResult Movies()
        {

            string moviesXml = this.SvcMovies.GetMovies();

            if (moviesXml.CompareTo("E") == 1)
            {
                return RedirectToAction("Error"); 
            }

            PackageViewBag(moviesXml);

            return View();
        }

        /// <summary>Post Method call for Movies page. Used for
        /// Searching for movies. Calls down to web service to get 
        /// a list of movies that matches the provided pieces of data.
        /// </summary>
        /// <param name="moviesViews"></param>
        /// <param name="returnUri"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Movies(Models.MoviesViews moviesViews, string returnUri)
        {
            int genreID = moviesViews.Genre.ID;
            string title = moviesViews.Movie.Title;
            string description = moviesViews.Movie.Description; 

            string moviesXml = this.SvcMovies.Search(title, description, genreID);
            if (moviesXml.CompareTo("E") == 1)
            {
                return RedirectToAction("Error");
            }

            PackageViewBag(moviesXml);

            return View();

        }

        /// <summary>Get request for AddMovie.  Simply readys data for dropdown box
        /// and returns view for addmovie page.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult AddMovie()
        {
            ViewBag.ModelListGenres = GetGenresList();
            return View();
        }

        /// <summary>Post call for adding a movie. Calls down to web service to 
        /// add a movie into the db.
        /// </summary>
        /// <param name="addMovieBase"></param>
        /// <param name="stringUri"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult AddMovie(Models.AddMovieBase addMovieBase, string stringUri)
        {
            int genreID = addMovieBase.Genre.ID;
            string title = addMovieBase.AddMovie.Title;
            string relDate = addMovieBase.AddMovie.ReleaseDate;
            string description = addMovieBase.AddMovie.Description;

            if (!CheckDate(relDate))
            {
                return View("Error");
            }

            if (ModelState.IsValid)
            {
                int rowsAffected = this.SvcMovies.AddNewMovie(title, description, relDate, genreID);
                if (rowsAffected == -1)
                {
                    return RedirectToAction("Error");
                }

                return RedirectToAction("Movies");
            }

            return View();
        }
        

        /// <summary>ViewResult for EditMovie. Called from the movies page
        ///with an id of the movie to be edited. Calls the web service
        ///to get the record for the movie to be edited and returns a model
        ///filled with the movie info to the view page to edit the movie.
        ///The EditMovie view populates texboxes and such with the info contained
        ///in the aformentioned model. 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ViewResult EditMovie(int id)
        {

            string movieXml = this.SvcMovies.GetMovie(id);
            if (movieXml.CompareTo("E") == 1)
            {
                return View("Error");
            }

            System.Xml.XmlDocument xmlDoc =
                    new System.Xml.XmlDocument();

            xmlDoc.LoadXml(movieXml);

            System.Xml.XmlNode xmlMovie = xmlDoc.SelectSingleNode("Movie");            

            Models.EditMovie movieModel = new Models.EditMovie();            

            movieModel.ID = id;
            movieModel.Title = xmlMovie["Title"].InnerText;
            movieModel.Description = xmlMovie["Description"].InnerText;
            movieModel.ReleaseDate = xmlMovie["ReleaseDate"].InnerText;
            
            movieModel.GenreID = int.Parse(xmlMovie["GenreID"].InnerText);

            ViewBag.MovieModel = movieModel;
            ViewBag.Description = movieModel.Description;
            ViewBag.ReleaseDate = movieModel.ReleaseDate;
            ViewBag.ModelListGenres = GetGenresList();
            Models.EditMovieBase retVal = new Models.EditMovieBase();

            List<Models.Genres> genres = GetGenresList();

            Models.Genres genreModel = new Models.Genres();
            foreach(Models.Genres genre in genres)
            {
                if(genre.ID == movieModel.GenreID)
                {
                    genreModel = genre;
                }
            }

            retVal.EditMovie = movieModel;
            retVal.Genre = genreModel;           
            
            return View(retVal);
        }
        
        /// <summary>Action result Post request for clicking submit on the editmovie view.
        /// takes in a model, gets the data in the model to pass to the webservice to 
        /// insert edit into the db.
        /// </summary>
        /// <param name="editMovieBase">Model containing movie to edit</param>
        /// <returns>Redirect to Movies action.</returns>
        [HttpPost]
        public ActionResult EditMovie(Models.EditMovieBase editMovieBase)
        {
            int movieId = editMovieBase.EditMovie.ID;
            string title = editMovieBase.EditMovie.Title;
            string description = editMovieBase.EditMovie.Description;
            string release = editMovieBase.EditMovie.ReleaseDate;
            int genreId = editMovieBase.Genre.ID;

            if (!CheckDate(release))
            {
                return View("Error");
            }

            if (ModelState.IsValid)
            {
                int rowsAffected = this.SvcMovies.EditMovie(movieId, title, description, release, genreId);
                if (rowsAffected == -1)
                {
                    return RedirectToAction("Error");
                }

                return RedirectToAction("Movies");
            }

            return View("Error");
        }

        /// <summary>Action Result for deleting movie. Called from movies page with an id when 
        /// delete button is pressed on a movie. Calles down to webservice to delete record.
        /// </summary>
        /// <param name="id">Id of movie to be deleted.</param>
        /// <returns>Redirect to Movies.</returns>
        public ActionResult DeleteMovie(int id)
        {
            int rowsAffected = this.SvcMovies.DeleteMovie(id);
            if (rowsAffected == -1)
            {
                return RedirectToAction("Error");
            }

            return RedirectToAction("Movies");
            
        }

        /// <summary>Get request for Genre page.
        /// </summary>
        /// <returns>View for Genre page.</returns>
        [HttpGet]
        public ActionResult AddGenre()
        {
            ViewBag.ModelListGenres = GetGenresList();
            return View();
        }
        
        /// <summary>Post request for clicking submit on genre page.
        /// Calls webservice with the genre name from the textbox.
        /// </summary>
        /// <param name="genre">Genre passed from the view.</param>
        /// <returns>Redirect to Genres page.</returns>
        [HttpPost]
        public ActionResult AddGenre(Models.AddGenre genre)
        {
            string name = genre.Name;

            if (ModelState.IsValid)
            {
                int rowsAffected = this.SvcMovies.AddNewGenre(name);
                if (rowsAffected == -1)
                {
                    return RedirectToAction("Error");
                }

                return RedirectToAction("AddGenre");
            }

            return View();
        }

        /// <summary>Deletes a genre. Called from AddGenre view when 
        /// delete link is pressed.  Called with an id of the genre to
        /// be deleted.
        /// </summary>
        /// <param name="id">Id of genre to be deleted.</param>
        /// <returns>Redirect to Genres page.</returns>
        public ActionResult DeleteGenre(int id)
        {
            int rowsAffected = this.SvcMovies.DeleteGenre(id);
            if (rowsAffected == -1)
            {
                return RedirectToAction("Error");
            }

            return RedirectToAction("AddGenre");
        }

        /// <summary>Generic error action. Simply returns an error view page.
        /// </summary>
        /// <returns>Basic Error view page.</returns>
        public ActionResult Error()
        {
            return View();
        }

        #endregion

        #region Helper methods

        // Helper method that pupulates a Genres Model List and returns it.
        // Calls down to webservice to get list of genres.
        private List<Models.Genres> GetGenresList()
        {
            string genresXml = this.SvcMovies.GetGenres();

            System.Xml.XmlDocument xmlDoc =
                new System.Xml.XmlDocument();

            xmlDoc.LoadXml(genresXml);

            System.Xml.XmlNodeList xmlGenresList = xmlDoc.SelectNodes("GenreList/Genre");

            Models.Genres genreModel = new Models.Genres();
            List<Models.Genres> modelList = new List<Models.Genres>();
            modelList.Add(genreModel);
            foreach (System.Xml.XmlNode node in xmlGenresList)
            {
                int id = int.Parse(node["ID"].InnerText);

                genreModel = new Models.Genres();
                genreModel.ID = id;
                genreModel.Name = node["Name"].InnerText;
                modelList.Add(genreModel);
            }
            return modelList;
        }

        // Helper method for packaging up xml. Takes in an xml string
        // and inflates it into a List of Movie Model objects. 
        // Then saves it, and Genres model list into the viewbag.
        private void PackageViewBag(string moviesXml)
        {
            System.Xml.XmlDocument xmlDoc =
                    new System.Xml.XmlDocument();

            xmlDoc.LoadXml(moviesXml);

            System.Xml.XmlNodeList xmlMovieList = xmlDoc.SelectNodes("MovieList/Movie");

            Models.Movie moviesModel = new Models.Movie();
            List<Models.Movie> modelList = new List<Models.Movie>();
            foreach (System.Xml.XmlNode node in xmlMovieList)
            {
                moviesModel = new Models.Movie();

                int id = int.Parse(node["id"].InnerText);
                moviesModel.ID = id;
                moviesModel.Title = node["Title"].InnerText;
                moviesModel.Description = node["Description"].InnerText;
                moviesModel.ReleaseDate = node["ReleaseDate"].InnerText;
                moviesModel.Genre = node["Genre"].InnerText;
                modelList.Add(moviesModel);
            }

            ViewBag.ModelListMovies = modelList;
            ViewBag.ModelListGenres = GetGenresList();
        }

        public bool CheckDate(string date)
        {
            DateTime dateTime = new DateTime();
            if (!DateTime.TryParse(date, out dateTime))
            {
                ViewBag.ErrorMessage = "That Date is impossible.";

                return false;
            }

            return true;
        }

        #endregion
    }
}
